package server

import (
	"common/database/config"
	"context"
	"exam_srv/internal/models/dao"
	pb "exam_srv/proto"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"strconv"
	"time"
)

type Server struct {
	pb.UnimplementedExamServer
}

type CreateExamRe struct {
	TestPaperName string `json:"testPaperName"`
	ClassName     string `json:"ClassName"`
	Id            int    `json:"id"`
}

func (c *Server) CreateExam(ctx context.Context, request *pb.CreateExamRequest) (*pb.CreateExamResponse, error) {
	var testPaper *dao.TestPaper
	var ok int
	db := config.DB.Begin()
	db.Where("id=?", request.PaperId).Find(&testPaper).Limit(1)
	if testPaper.ID == 0 {
		ok = 2
	} else {
		ok = 1
	}
	var examResponse []*CreateExamRe
	config.DB.Raw("select tp.test_paper_name,tp.class_name,tpq.id "+
		"from c_test_paper tp "+
		"join c_test_paper_question tpq "+
		"on tp.id=tpq.test_paper_id "+
		"where tp.id=?", request.PaperId).Scan(&examResponse)
	num := len(examResponse)
	now := time.Now()
	var exam dao.Exam
	for _, i := range examResponse {
		exam = dao.Exam{
			TestPaperName: i.TestPaperName,
			PaperCate:     i.ClassName,
			CreateTime:    now,
			Num:           num,
			Ok:            ok,
			UserId:        int(request.UserId),
		}
		break
	}
	err := db.Create(&exam).Error
	if err != nil {
		db.Rollback()
		return nil, errors.New("考试创建失败")
	}
	examPaper := dao.ExamPaper{
		ExamId:  int(exam.ID),
		PaperId: int(request.PaperId),
	}
	err = db.Create(&examPaper).Error
	if err != nil {
		db.Rollback()
		return nil, errors.New("考试创建失败")
	}
	for _, i := range request.UserIds {
		one := dao.ExamStudent{
			ExamId: int(exam.ID),
			UserId: int(i),
		}
		err = db.Create(&one).Error
		if err != nil {
			db.Rollback()
			return nil, errors.New("考试创建失败")
		}
	}
	db.Commit()
	key := "exam_:" + strconv.Itoa(int(exam.ID))
	config.Rdb.Set(config.Ctx, key, exam.ID, time.Minute*time.Duration(request.Time))
	return &pb.CreateExamResponse{Id: int64(exam.ID)}, nil
}

func (c *Server) ListExam(ctx context.Context, request *pb.ListExamRequest) (*pb.ListExamResponse, error) {
	var exam []*dao.Exam
	var num []int
	config.DB.Find(&exam)
	for _, d := range exam {
		key := "exam_:" + strconv.Itoa(int(d.ID))
		val := config.Rdb.Get(config.Ctx, key).Val()
		if val != "" {
			num = append(num, int(d.ID))
		}
	}
	var sli []*pb.Exams
	for _, i := range num {
		var exams dao.Exam
		config.DB.Raw("SELECT * "+
			"from c_exam e where e.id=?", i).Scan(&exams)
		one := pb.Exams{
			Type:          int64(exams.Type),
			TestPaperName: exams.TestPaperName,
			PaperCate:     exams.PaperCate,
			QuestionType:  int64(exams.QuestionType),
			CreateTime:    exams.CreateTime.String(),
			Num:           int64(exams.Num),
			Ok:            int64(exams.Ok),
			UserId:        int64(exams.UserId),
		}
		sli = append(sli, &one)
	}
	return &pb.ListExamResponse{Exam: sli}, nil
}

func (c *Server) FindExam(ctx context.Context, request *pb.FindExamRequest) (*pb.FindExamResponse, error) {
	var exam *dao.Exam
	config.DB.Raw("SELECT * "+
		"from c_exam e where e.id=?", request.ExamId).Scan(&exam)
	one := &pb.Exams{
		Type:          int64(exam.Type),
		TestPaperName: exam.TestPaperName,
		PaperCate:     exam.PaperCate,
		QuestionType:  int64(exam.QuestionType),
		CreateTime:    exam.CreateTime.String(),
		Num:           int64(exam.Num),
		Ok:            int64(exam.Ok),
		UserId:        int64(exam.UserId),
	}
	return &pb.FindExamResponse{Exam: one}, nil
}

type ExamBeginRe struct {
	Id         int       `json:"id"`
	UserId     int       `json:"userId"`
	CreateTime time.Time `json:"create_time"`
}

func (c *Server) ExamBegin(ctx context.Context, request *pb.ExamBeginRequest) (*pb.ExamBeginResponse, error) {
	var exam *dao.Exam
	config.DB.Where("id=?", request.ExamId).Find(&exam).Limit(1)
	if exam.ID == 0 {
		return nil, errors.New("暂无该考试")
	}
	var examBegin *ExamBeginRe
	config.DB.Raw("SELECT e.id,s.user_id,e.create_time "+
		"from c_exam e join c_exam_student s on e.id=s.exam_id "+
		"WHERE e.id=? and s.user_id=?", request.ExamId, request.UserId).Scan(&examBegin)
	if examBegin.Id == 0 {
		return nil, errors.New("您暂无该考试资格")
	}
	you := dao.ExamBegin{
		ExamId: int(request.ExamId),
		UserId: int(request.UserId),
		Yes:    "",
		Scan:   90,
	}
	config.DB.Create(&you)
	now := time.Now().Minute() - examBegin.CreateTime.Minute()
	if now > 10 {
		timer1 := time.NewTimer(time.Second * 2)
		<-timer1.C
		zap.S().Info("考试还有10分钟结束")
		return &pb.ExamBeginResponse{}, nil
	}
	zap.S().Infof("考试还有%v结束", now)
	return &pb.ExamBeginResponse{}, nil
}

func (c *Server) ExamRank(ctx context.Context, request *pb.ExamRankRequest) (*pb.ExamRankResponse, error) {
	var exam []dao.ExamBegin
	config.DB.Where("exam_id=?", request.ExamId).Find(&exam).Order("scan DESC").Limit(10)
	var sli []*pb.Rank
	for _, b := range exam {
		one := pb.Rank{
			Speak: "你真棒",
			Id:    int64(b.UserId),
		}
		sli = append(sli, &one)
	}
	return &pb.ExamRankResponse{Rank: sli}, nil
}
